using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace WinCANTool
{

    

    public partial class FlashWindow1319 : Form
    {

        public string StringData1;
        public string StringIn;
        public char[] StringData = new char[60];
 
  
    public void SegmentTransfer()
    {
        if (SegmentWrite)
            OpArgs.ReturnOpValue = (int) Segment_Transfer_Write(CommandObjectIndex, StringData1, NodeId);
        else
            OpArgs.ReturnOpValue = (int) Segment_Transfer_Read(CommandObjectIndex, StringData, NodeId);
        FlashOpOn = false;
        //SendFlashEndEvent(Args);
        SendMessageEndEvent(OpArgs);

    }

        
/***************************************************************************
DESCRIPTION:
	Segment_Transfer_Read:
	Function used to upload strings from CAN objects.  	  
	
ARGS:
	long index;  CAN Object index combined with the subindex.
	char *StringData; String that will be read from CAN object.
	int NodeId;  	Value from 1 to 127 used in the indentifier for node communication.
	
RETURNS:
	long Status;   If the operation was sucessful then the returned value = 0,
					otherwise the Status value corresponds to a NI error. Negative
					values are severe, and positive values are warnings.
		
****************************************************************************/


long Segment_Transfer_Read(long index, char[] StringData, int NodeId)
	{
	
	
	int i = 0; //j = 0, k = 0;
	//NCTYPE_STATUS   Status;
	
	int SDO_Data_Out;
	int SDO_Data_In;
	int ReturnVal;
	//int SendByteCount;
	//int TempData;
	int SegmentByteCount;

	int CharCount;
	int LastSegment;
	byte Toggle;
	int SegmentCount;
	byte ClientCommand, ServerCommand, MessageType = 0, ByteCount, StartByte;
	char[] SegmentData = new char[7];
	int LastBytes;
    //bool Expedite = false;

/*******************************  SDO Segment Upload Initiate  **************************************/


    SDO_Data_In = 0;
	SDO_Data_Out = 0;
    index = CommandObjectIndex;
    FlashOpOn = true;
    SDOVarInit();


	ReturnVal = SendSDOInitiate(index, SDO_Data_Out, ref SDO_Data_In, ref MessageType, NodeId, 
        0x40, 0x41, ref SegmentData);

	if (ReturnVal != 0)
		return ReturnVal;

    if ((MessageType & 0x03) == 0x03)
    {
        //Expedite = true;
        ByteCount = (byte) ((MessageType & 0x0C) >> 2);
        CharCount = 0;
        LastBytes = ByteCount + 3;
        StartByte = 3;
    }
    else
    {
        StartByte = 0;
        SegmentByteCount = SDO_Data_In & 0xFF;


        /*****************************    Upload complete segments    ***************************************/

        CharCount = 0;
        Toggle = 2;


        if (SegmentByteCount == 7)
        {
            SegmentCount = 0;
            LastBytes = 0;
        }
        else
        {
            SegmentCount = SegmentByteCount / 7;
            LastBytes = 7 - SegmentByteCount % 7;
        }


        if (LastBytes == 0)
            LastSegment = 1;
        else
            LastSegment = 0;


        while (SegmentCount > LastSegment)
        {

            if ((Toggle % 2) == 0)
            {
                ClientCommand = 0x60;
                ServerCommand = 0x00;
            }
            else
            {
                ClientCommand = 0x70;
                ServerCommand = 0x10;
            }

            ReturnVal = GetSubBlock(NodeId, ClientCommand, ServerCommand, ref SegmentData);
            if (ReturnVal != 0)
                return ReturnVal;

            for (i = 0; i < 7; i++)
            {
                StringData[i + CharCount] = SegmentData[i];
                StringData1 += SegmentData[i];
            }
            Toggle++;
            CharCount += 7;
            SegmentCount--;

        }

        /******************************    Upload last segment     *******************************************/

        if ((Toggle % 2) == 0)
        {
            ClientCommand = 0x60;
            ServerCommand = (byte)(0x00 | (LastBytes << 1) | 0x01);
        }
        else
        {
            ClientCommand = 0x70;
            ServerCommand = (byte)(0x10 | (LastBytes << 1) | 0x01);
        }

        ReturnVal = GetSubBlock(NodeId, ClientCommand, ServerCommand, ref SegmentData);
        if (ReturnVal != 0)
            return ReturnVal;
    }
        
    
    
    for (i = 0; (i < (7 - LastBytes)); i++)
    {
        StringData[i + CharCount] = SegmentData[i + StartByte];
        StringData1 += SegmentData[i + StartByte];
    }

    StringData[i + CharCount] = '\0';
	
    return ReturnVal;


    }




/***************************************************************************
DESCRIPTION:
	Segment_Transfer_Write:
	Function used to download strings to CAN objects.  	  
	
ARGS:
	long index;  CAN Object index combined with the subindex.
	char *StringData; String that will be read from CAN object.
	int NodeId;  	Value from 1 to 127 used in the indentifier for node communication.
	
RETURNS:
	long Status;   If the operation was sucessful then the returned value = 0,
					otherwise the Status value corresponds to a NI error. Negative
					values are severe, and positive values are warnings.
		
****************************************************************************/


long Segment_Transfer_Write(long index, string StringData, int NodeId)
	{


        int i = 0; //j = 0, k = 0;
	
	int SDO_Data_Out;
	int SDO_Data_In;
	int ReturnVal;
	//int SendByteCount;
	//int TempData;
	int SegmentByteCount;

	int CharCount,StringLen;
	int LastSegment;
	byte Toggle;
	int SegmentCount;
	byte ClientCommand, ServerCommand, MessageType;
    char[] SegmentData = new char[7];
	int LastBytes;

/*******************************  SDO Segment Download Initiate  ***********************************/

    SDO_Data_In = 0;
    SDO_Data_Out = 0;
    index = CommandObjectIndex;
    FlashOpOn = true;
    SDOVarInit();
    StringLen = StringData.Length;	
	SDO_Data_Out = StringLen;
    MessageType = 0;


    if (StringLen <= 4)
    {
        ClientCommand = (byte) ((0x01 << 5) | ((4 - StringLen) << 3) | 0x03);
        for (int l = 0; l < StringLen; l++)
        {
            SegmentData[3 + l] = StringData[l];
        }
    }
    else
    {
        ClientCommand = 0x21;
    }
    
    ReturnVal = SendSDOInitiate(index, SDO_Data_Out, ref SDO_Data_In, ref MessageType, NodeId, 
         ClientCommand, 0x60, ref SegmentData);

	if (ReturnVal != 0)
		return ReturnVal;

    if (StringLen > 4)
    {

        SegmentByteCount = SDO_Data_In & 0xFF;

        if (SegmentByteCount != StringLen)
            return -1;


        /***************************    Download complete segments    *************************************/

        CharCount = 0;
        Toggle = 2;
        SegmentCount = SegmentByteCount / 7;
        LastBytes = 7 - SegmentByteCount % 7;

        if (LastBytes == 0)
            LastSegment = 1;
        else
            LastSegment = 0;


        while (SegmentCount > LastSegment)
        {

            if ((Toggle % 2) == 0)
            {
                ClientCommand = 0x00;
                ServerCommand = 0x20;
            }
            else
            {
                ClientCommand = 0x10;
                ServerCommand = 0x30;
            }


            for (i = 0; i < 7; i++)
            {
                SegmentData[i] = StringData[i + CharCount];
            }

            ReturnVal = WriteSubBlock(NodeId, ClientCommand, ServerCommand, ref SegmentData);

            if (ReturnVal != 0)
                return ReturnVal;

            Toggle++;
            CharCount += 7;
            SegmentCount--;

        }

        /****************************    Download last segment     *****************************************/

        if ((Toggle % 2) == 0)
        {
            ClientCommand = (byte)(0x00 | (LastBytes << 1) | 0x01);
            ServerCommand = 0x20;
        }
        else
        {
            ClientCommand = (byte)(0x10 | (LastBytes << 1) | 0x01);
            ServerCommand = 0x30;
        }


        for (i = 0; i < 7; i++)
        {
            SegmentData[i] = '\0';
        }


        for (i = 0; (i < (7 - LastBytes)); i++)
        {
            SegmentData[i] = StringData[i + CharCount];
        }

        ReturnVal = WriteSubBlock(NodeId, ClientCommand, ServerCommand, ref SegmentData);
        if (ReturnVal != 0)
            return ReturnVal;
    }
	
	return ReturnVal;

}







/***************************************************************************
DESCRIPTION:
	SendSDOInitiate:
	Function used to initiate an SDO Block Transfer.  
	A MOSI message is sent, and a MISO message is read in less than 25 ms.   	  
	
ARGS:
	long index;  CAN Object index combined with the subindex.  
	int SDO_TX_Data;   SDO data that is transmitted.
	int NodeId;  Value from 1 to 127 used in the indentifier for node communication.	
	
RETURNS:
	long Status;   If the operation was sucessful then the returned value = 0,
					otherwise the Status value corresponds to a NI error. Negative
					values are severe, and positive values are warnings.
					If there is no MISO message returned on the CAN bus, then there 
					is a NI error returned from this function.	  
		
****************************************************************************/

        int SendSDOInitiate(long index, int SDO_TX_Data, ref int SDO_RX_Data, ref byte MessageType, int NodeId, 
            byte ClientCommand, byte ServerCommand, ref char[] SeqData)
        {

            int  ReturnVal;
            CanMessageOut.DATA = new byte[8];
            CanMessageIn.DATA = new byte[8];

            CanMessageOut.LEN = 8;
            CanMessageOut.ID = 0x600 + (uint)NodeId;
            CanMessageOut.MSGTYPE = 0;


                CanMessageOut.DATA[0] = ClientCommand;		                                //	CS_Byte 
                CanMessageOut.DATA[1] = (byte)((index & 0x0000FF00) >> 8);			//	LSByte of Index
                CanMessageOut.DATA[2] = (byte)((index & 0x00FF0000) >> 16);			//	MSByte of Index
                CanMessageOut.DATA[3] = (byte)(index & 0x000000FF);					//	SubIndex
            
            
            
            if (SDO_TX_Data <= 4)
            {
                CanMessageOut.DATA[4] = (byte)SeqData[3];			// 	LSByte of LSWord
                CanMessageOut.DATA[5] = (byte)SeqData[4]; 	        // 	MSByte of LSWord
                CanMessageOut.DATA[6] = (byte)SeqData[5];	        // 	LSByte of MSWord
                CanMessageOut.DATA[7] = (byte)SeqData[6];	        // 	MSByte of MSWord


            }

            else
            {
                CanMessageOut.DATA[4] = (byte)(SDO_TX_Data & 0x000000FF);			// 	LSByte of LSWord
                CanMessageOut.DATA[5] = (byte)((SDO_TX_Data & 0x0000FF00) >> 8); 	// 	MSByte of LSWord
                CanMessageOut.DATA[6] = (byte)((SDO_TX_Data & 0x00FF0000) >> 16);	// 	LSByte of MSWord
                CanMessageOut.DATA[7] = (byte)((SDO_TX_Data & 0xFF000000) >> 24);	// 	MSByte of MSWord
            }

            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);


            MessageOk = false;
            ReadCount = WAIT_TIME;


            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                if (ReadCount-- == 0)
                {
                    //SendFlashEndEvent(Args);
                    ReturnValue = -99;
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            MessageType = CanMessageIn.DATA[0];
            SDO_RX_Data = CanMessageIn.DATA[4] + (CanMessageIn.DATA[5] << 8) + (CanMessageIn.DATA[6] << 16) + (CanMessageIn.DATA[7] << 24);

            if ((CanMessageIn.DATA[0] & 0xF0) != (ServerCommand & 0xF0))
            {
                ReturnVal = -1;
            }
            else
            {
                ReturnVal = 0;
            }

            SeqData[0] = (char)CanMessageIn.DATA[1];
            SeqData[1] = (char)CanMessageIn.DATA[2];
            SeqData[2] = (char)CanMessageIn.DATA[3];
            SeqData[3] = (char)CanMessageIn.DATA[4];
            SeqData[4] = (char)CanMessageIn.DATA[5];
            SeqData[5] = (char)CanMessageIn.DATA[6];
            SeqData[6] = (char)CanMessageIn.DATA[7];

            return ReturnVal;

        }


        

/***************************************************************************
DESCRIPTION:
	GetSubBlock:
	Function used to send one segment.  
	   	  
	
ARGS:
	
    int NodeId;  Value from 1 to 127 used in the indentifier for node communication.  
	char ClientCommand;  First Byte of send message.
	char ServerCommand;	 Expected first Byte of received message.
	char *SeqData;  address of 7 bytes of segment data.
	
	
RETURNS:
	long Status;   If the operation was sucessful then the returned value = 0,
					otherwise the Status value corresponds to a NI error. Negative
					values are severe, and positive values are warnings.
					If there is no MISO message returned on the CAN bus, then there 
					is a NI error returned from this function.	  
		
****************************************************************************/




        int GetSubBlock(int NodeId, byte ClientCommand, byte ServerCommand, ref char[] SeqData)
        {

            int  ReturnVal;


            //CanMessageOut.Data = new byte[8];
            //CanMessageIn.Data = new byte[8];

            CanMessageOut.LEN = 8;
            CanMessageOut.ID = 0x600 + (uint)NodeId;
            CanMessageOut.MSGTYPE = 0;


            CanMessageOut.DATA[0] = ClientCommand;		//	CS_Byte
            CanMessageOut.DATA[1] = 0;			        //	Byte 1
            CanMessageOut.DATA[2] = 0;			        //	Byte 2
            CanMessageOut.DATA[3] = 0;			        //	Byte 3
            CanMessageOut.DATA[4] = 0;			        // 	Byte 4
            CanMessageOut.DATA[5] = 0; 	                // 	Byte 5
            CanMessageOut.DATA[6] = 0;	                // 	Byte 6
            CanMessageOut.DATA[7] = 0;	                // 	Byte 7


            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);


            MessageOk = false;
            ReadCount = WAIT_TIME;


            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                if (ReadCount-- == 0)
                {
                    //SendFlashEndEvent(Args);
                    ReturnVal = -99;
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);



            if (CanMessageIn.DATA[0] != ServerCommand)
            {
                ReturnVal = -1;
            }
            else
            {
                ReturnVal = 0;
            }

            SeqData[0] = (char)CanMessageIn.DATA[1];
            SeqData[1] = (char)CanMessageIn.DATA[2];
            SeqData[2] = (char)CanMessageIn.DATA[3];
            SeqData[3] = (char)CanMessageIn.DATA[4];
            SeqData[4] = (char)CanMessageIn.DATA[5];
            SeqData[5] = (char)CanMessageIn.DATA[6];
            SeqData[6] = (char)CanMessageIn.DATA[7];

            return ReturnVal;



        }


/***************************************************************************
DESCRIPTION:
    WriteSubBlock:
    Function used to write one segment.  
  

ARGS:

    int NodeId;  Value from 1 to 127 used in the indentifier for node communication.  
    char ClientCommand;  First Byte of send message.
    char ServerCommand;	 Expected first Byte of received message.
    char *SeqData;  address of 7 bytes of segment data.


RETURNS:
    long Status;   If the operation was sucessful then the returned value = 0,
                    otherwise the Status value corresponds to a NI error. Negative
                    values are severe, and positive values are warnings.
                    If there is no MISO message returned on the CAN bus, then there 
                    is a NI error returned from this function.	  

****************************************************************************/

int WriteSubBlock(int NodeId, byte ClientCommand, byte ServerCommand, ref char[] SeqData)
{

		int i, ReturnVal;
		
		
	        CanMessageOut.LEN = 8;
            CanMessageOut.ID = 0x600 + (uint)NodeId;
            CanMessageOut.MSGTYPE = 0;

		CanMessageOut.DATA[0] = ClientCommand;		        //	CS_Byte
		CanMessageOut.DATA[1] = (byte)SeqData[0];			//	Byte 1
        CanMessageOut.DATA[2] = (byte)SeqData[1];			//	Byte 2
        CanMessageOut.DATA[3] = (byte)SeqData[2];			//	Byte 3
        CanMessageOut.DATA[4] = (byte)SeqData[3];			// 	Byte 4
        CanMessageOut.DATA[5] = (byte)SeqData[4]; 	        // 	Byte 5
        CanMessageOut.DATA[6] = (byte)SeqData[5];	        // 	Byte 6
        CanMessageOut.DATA[7] = (byte)SeqData[6];	        // 	Byte 7

		
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);


            MessageOk = false;
            ReadCount = WAIT_TIME;


            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                if (ReadCount-- == 0)
                {
                    //SendFlashEndEvent(Args);
                    ReturnVal = -99;
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);


            if (CanMessageIn.DATA[0] != ServerCommand)
			{
				ReturnVal = -1;
			}
		else
			{
				ReturnVal = 0;
			}

		for (i = 0; i < 7; i++)
		    {
                if (CanMessageIn.DATA[i + 1] != SeqData[i])
			       ReturnVal = -1;
			}	
		
		return ReturnVal;
}









    }
}
